﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using BCCommon;
using BCEntity.Chats;
using System.Linq;

namespace BCData.Chats
{
    public class MessageReceiverData : IMessageReceiverData
    {
        private readonly IDatabaseContext databaseContext;

        public MessageReceiverData(IDatabaseContext databaseContext)
        {
            this.databaseContext=databaseContext;
        }

        public async Task<IEnumerable<MessageReceiverEntity>> GetMessageReceiversByMessageIdAsync(IEnumerable<long> messageIds)
        {
            if (!messageIds.Any())
            {
                return new MessageReceiverEntity[0];
            }

            string sql = typeof(MessageReceiverEntity).GetSelectSql();

            return await this.databaseContext.Slave.QueryAsync<MessageReceiverEntity>($"{sql} WHERE MessageId IN ?MessageIds", new { messageIds });
        }

        public Task<MessageReceiverEntity> GetMessageReceiverAsync(string receiveUserId, long messageId)
        {
            string sql = typeof(MessageReceiverEntity).GetSelectSql();

            return this.databaseContext.Slave.QueryFirstOrDefaultAsync<MessageReceiverEntity>($"{sql} WHERE MessageId = ?MessageId AND ReceiveUserId = ?ReceiveUserId", new { messageId, receiveUserId });
        }

        public Task InsertAllAsync(IEnumerable<MessageReceiverEntity> entities)
        {
            return this.databaseContext.Master.InsertAllAsync(entities, this.databaseContext.Transaction);
        }

        public Task<MessageReceiverEntity> UpdateAsync(MessageReceiverEntity entity)
        {
            return this.databaseContext.Master.UpdateAsync(entity, this.databaseContext.Transaction);
        }

        public Task SetAsDeleted(string receiveUserId, long messageId)
        {
            const string sql = "UPDATE chat_messagereceiver SET Deleted = true WHERE MessageId = ?MessageId AND ReceiveUserId = ?ReceiveUserId";

            return this.databaseContext.Master.ExecuteAsync(sql, new { messageId, receiveUserId }, this.databaseContext.Transaction);
        }

        public Task UpdateReceiptTimeAsync(string receiveUserId, long messageId)
        {
            const string sql = "UPDATE chat_messagereceiver SET ReceiptTime = ?ReceiptTime WHERE MessageId = ?MessageId AND ReceiveUserId = ?ReceiveUserId AND ReadTime IS NULL";

            return this.databaseContext.Master.ExecuteAsync(sql, new { ReceiptTime = DateTime.Now, messageId, receiveUserId }, this.databaseContext.Transaction);
        }

        public Task UpdateAllReadTimeAsync(string receiveUserId, long threadId)
        {
            const string sql = "UPDATE chat_messagereceiver SET ReadTime = ?ReadTime WHERE ThreadId = ?ThreadId AND ReceiveUserId = ?ReceiveUserId AND ReadTime IS NULL";

            return this.databaseContext.Master.ExecuteAsync(sql, new { ReadTime = DateTime.Now, receiveUserId, threadId }, this.databaseContext.Transaction);
        }

        public Task UpdateAllReadTimeAsync(string receiveUserId, long threadId, long maxMessageId)
        {
            const string sql = "UPDATE chat_messagereceiver SET ReadTime = ?ReadTime WHERE ThreadId = ?ThreadId AND MessageId <= ?MaxMessageId AND ReceiveUserId = ?ReceiveUserId AND ReadTime IS NULL";

            return this.databaseContext.Master.ExecuteAsync(sql, new { ReadTime = DateTime.Now, receiveUserId, threadId, maxMessageId }, this.databaseContext.Transaction);
        }

        public Task UpdateReadTimeAsync(string receiveUserId, long threadId, long messageId)
        {
            const string sql = "UPDATE chat_messagereceiver SET ReadTime = ?ReadTime WHERE ThreadId = ?ThreadId AND MessageId = ?MessageId AND ReceiveUserId = ?ReceiveUserId AND ReadTime IS NULL";

            return this.databaseContext.Master.ExecuteAsync(sql, new { ReadTime = DateTime.Now, receiveUserId, threadId, messageId }, this.databaseContext.Transaction);
        }
    }
}
